//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

import { gen_ssh_key, list_ssh_key_name } from "@/api/local_repo";
import { resolve } from "@tauri-apps/api/path";
import { Button, Divider, Form, Input, List, message, Modal, Popover, Space } from "antd";
import React, { useEffect, useState } from "react";
import { homeDir } from '@tauri-apps/api/path';
import { readTextFile, exists as existPath, createDir, writeTextFile, removeFile } from '@tauri-apps/api/fs';
import { writeText } from '@tauri-apps/api/clipboard';
import { useStores } from "@/hooks";
import { USER_TYPE_ATOM_GIT, USER_TYPE_GIT_CODE, USER_TYPE_GITEE } from "@/api/user";
import { MoreOutlined } from "@ant-design/icons";
import { list_ssh_key as list_atomgit_ssh_key, add_ssh_key as add_atomgit_ssh_key, remove_ssh_key as remove_atomgit_ssh_key } from "@/api/atomgit/ssh";
import { list_ssh_key as list_gitee_ssh_key, add_ssh_key as add_gitee_ssh_key, remove_ssh_key as remove_gitee_ssh_key } from "@/api/gitee/ssh";
import { list_ssh_key as list_gitcode_ssh_key, add_ssh_key as add_gitcode_ssh_key, remove_ssh_key as remove_gitcode_ssh_key } from "@/api/gitcode/ssh";
import { open as shell_open } from '@tauri-apps/api/shell';
import { useTranslation } from "react-i18next";

export interface SshKeyListModalProps {
    onCount: (count: number) => void;
    onClose: () => void;
}

interface LocalSshKey {
    name: string;
    pubKey: string;
}

interface RemoteSshKey {
    key: string;
    id: number | string;
    title: string;
}

const SshKeyListModal = (props: SshKeyListModalProps) => {
    const { t } = useTranslation();

    const userStore = useStores('userStore');

    const [localSshList, setLocalSshList] = useState<LocalSshKey[]>([]);
    const [remoteSshList, setRemoteSshList] = useState<RemoteSshKey[]>([]);
    const [inGen, setInGen] = useState(false);
    const [newSshName, setNewSshName] = useState("");

    const loadLocalSshList = async () => {
        const home = await homeDir();
        const sshNameList = await list_ssh_key_name();
        const tmpList: LocalSshKey[] = [];
        for (const sshName of sshNameList) {
            const path = await resolve(home, ".ssh", sshName + ".pub");
            const content = await readTextFile(path);
            tmpList.push({
                name: sshName,
                pubKey: content.trim(),
            });
        }
        setLocalSshList(tmpList);
        props.onCount(sshNameList.length);
        if (sshNameList.length == 0) {
            setNewSshName("id_rsa")
        }
    };

    const loadRemoteSshList = async () => {
        if (userStore.userInfo.userType == USER_TYPE_ATOM_GIT) {
            const keyList = await list_atomgit_ssh_key(userStore.userInfo.extraToken);
            setRemoteSshList(keyList);
        } else if (userStore.userInfo.userType == USER_TYPE_GITEE) {
            const keyList = await list_gitee_ssh_key(userStore.userInfo.extraToken);
            setRemoteSshList(keyList);
        } else if (userStore.userInfo.userType == USER_TYPE_GIT_CODE) {
            const keyList = await list_gitcode_ssh_key(userStore.userInfo.extraToken);
            setRemoteSshList(keyList);
        }
    };

    const findRemoteSsh = (pubKey: string) => {
        const parts = pubKey.split(" ");
        const realkey = parts[1];
        return remoteSshList.find(item => item.key.includes(realkey));
    };

    const genNewSshKey = async () => {
        //检查.ssh目录
        const home = await homeDir();
        const sshDirPath = await resolve(home, ".ssh");
        const exist = await existPath(sshDirPath);
        if (!exist) {
            await createDir(sshDirPath);
        }
        //检查目标文件是否存在
        const privKeyPath = await resolve(home, ".ssh", newSshName);
        const exist2 = await existPath(privKeyPath);
        if (exist2) {
            message.error(t("text.existSshKey"));
            return;
        }
        try {
            setInGen(true);
            const keyPair = await gen_ssh_key();
            await writeTextFile(privKeyPath, keyPair.priv_key);
            await writeTextFile(privKeyPath + ".pub", keyPair.pub_key);
            await loadLocalSshList();
            message.info(t("text.genSuccess"));
            setNewSshName("");
        } finally {
            setInGen(false);
        }
    };

    const removeSshKey = async (sshName: string) => {
        const home = await homeDir();
        const sshDirPath = await resolve(home, ".ssh");
        let exist = await existPath(sshDirPath);
        if (!exist) {
            return;
        }
        const privKeyPath = await resolve(home, ".ssh", sshName);
        const pubKeyPath = await resolve(home, ".ssh", sshName + ".pub");
        exist = await existPath(privKeyPath);
        if (exist) {
            await removeFile(privKeyPath);
        }
        exist = await existPath(pubKeyPath);
        if (exist) {
            await removeFile(pubKeyPath);
        }
        await loadLocalSshList();
        message.info(t("text.removeSuccess"));
    };

    const addRemoteKey = async (title: string, key: string) => {
        if (userStore.userInfo.userType == USER_TYPE_ATOM_GIT) {
            try {
                await add_atomgit_ssh_key(userStore.userInfo.extraToken, title, key);
                message.info(t("text.deploySuccess"));
            } catch (e) {
                message.error(t("text.deploySshKeyFail"));
                return;
            }
        } else if (userStore.userInfo.userType == USER_TYPE_GITEE) {
            try {
                await add_gitee_ssh_key(userStore.userInfo.extraToken, title, key);
                message.info(t("text.deploySuccess"));
            } catch (e) {
                message.error(t("text.deploySshKeyFail"));
                return;
            }
        } else if (userStore.userInfo.userType == USER_TYPE_GIT_CODE) {
            try {
                await add_gitcode_ssh_key(userStore.userInfo.extraToken, title, key);
                message.info(t("text.deploySuccess"));
            } catch (e) {
                console.log(e);
                message.error(t("text.deploySshKeyFail"));
                return;
            }
        }
        await loadRemoteSshList();
    };

    const delRemoteKey = async (pubKey: string) => {
        const remoteKey = findRemoteSsh(pubKey);
        if (remoteKey == undefined) {
            return;
        }
        if (userStore.userInfo.userType == USER_TYPE_ATOM_GIT) {
            await remove_atomgit_ssh_key(userStore.userInfo.extraToken, remoteKey.id);
            message.info(t("text.unDeploySuccess"));
        } else if (userStore.userInfo.userType == USER_TYPE_GITEE) {
            await remove_gitee_ssh_key(userStore.userInfo.extraToken, remoteKey.id);
            message.info(t("text.unDeploySuccess"));
        } else if (userStore.userInfo.userType == USER_TYPE_GIT_CODE) {
            await remove_gitcode_ssh_key(userStore.userInfo.extraToken, remoteKey.id);
            message.info(t("text.unDeploySuccess"));
        }
        await loadRemoteSshList();
    };

    useEffect(() => {
        loadLocalSshList();
        loadRemoteSshList();
    }, []);

    return (
        <Modal open mask={false} title={
            <span>
                <span>
                    {t("text.sshKeys")}&nbsp;
                    {userStore.userInfo.userType == USER_TYPE_ATOM_GIT && (
                        <a onClick={e => {
                            e.stopPropagation();
                            e.preventDefault();
                            shell_open("https://atomgit.com/-/profile/keys");
                        }}>{t("text.viewAtomGitKey")}</a>
                    )}
                    {userStore.userInfo.userType == USER_TYPE_GIT_CODE && (
                        <a onClick={e => {
                            e.stopPropagation();
                            e.preventDefault();
                            shell_open("https://gitcode.com/setting/key-ssh");
                        }}>{t("text.viewGitCodeKey")}</a>
                    )}
                    {userStore.userInfo.userType == USER_TYPE_GITEE && (
                        <a onClick={e => {
                            e.stopPropagation();
                            e.preventDefault();
                            shell_open("https://gitee.com/profile/sshkeys");
                        }}>{t("text.viewGiteeKey")}</a>
                    )}
                </span>
            </span>} footer={null}
            bodyStyle={{ maxHeight: "calc(100vh - 300px)", overflowY: "scroll" }}
            onCancel={e => {
                e.stopPropagation();
                e.preventDefault();
                props.onClose();
            }}>
            <List rowKey="name" dataSource={localSshList} renderItem={localItem => (
                <List.Item extra={
                    <Space>
                        {[USER_TYPE_ATOM_GIT, USER_TYPE_GITEE, USER_TYPE_GIT_CODE].includes(userStore.userInfo.userType) && (
                            <>
                                {findRemoteSsh(localItem.pubKey) !== undefined && (
                                    <Button type="link" style={{ minWidth: 0, padding: "0px 0px" }} title="从远程账号移除对应公钥"
                                        onClick={e => {
                                            e.stopPropagation();
                                            e.preventDefault();
                                            delRemoteKey(localItem.pubKey);
                                        }}>{t("text.undeploy")}</Button>
                                )}
                                {findRemoteSsh(localItem.pubKey) === undefined && (
                                    <Button type="link" style={{ minWidth: 0, padding: "0px 0px" }} title="把公钥加入远程账号"
                                        onClick={e => {
                                            e.stopPropagation();
                                            e.preventDefault();
                                            addRemoteKey(localItem.name, localItem.pubKey);
                                        }}>{t("text.deploy")}</Button>
                                )}
                            </>
                        )}
                        <Button type="link" style={{ minWidth: 0, padding: "0px 0px" }} onClick={e => {
                            e.stopPropagation();
                            e.preventDefault();
                            writeText(localItem.pubKey).then(() => message.info(t("text.copySuccess")));
                        }}>{t("text.copyPubKey")}</Button>
                        <Popover placement="bottom" trigger="click" content={
                            <Space direction="vertical">
                                <Button type="link" danger disabled={localItem.name.startsWith("id_")} onClick={e => {
                                    e.stopPropagation();
                                    e.preventDefault();
                                    removeSshKey(localItem.name);
                                }} title={localItem.name.startsWith("id_") ? "无法删除id_开头的密钥" : ""}>删除</Button>
                            </Space>
                        }>
                            <MoreOutlined />
                        </Popover>
                    </Space>
                }>
                    {localItem.name}
                </List.Item>
            )} />
            <Divider />
            <Form>
                <Form.Item label={t("text.sshKeyName")} help={
                    <>
                        {inGen == true && t("text.inGenKey")}
                    </>
                }>
                    <Space>
                        <Input style={{ width: "320px" }} value={newSshName} disabled={inGen} onChange={e => {
                            e.stopPropagation();
                            e.preventDefault();
                            setNewSshName(e.target.value.trim());
                        }} />
                        <Button type="primary" disabled={inGen || newSshName == ""} onClick={e => {
                            e.stopPropagation();
                            e.preventDefault();
                            genNewSshKey();
                        }}>{t("text.genSshKey")}</Button>
                    </Space>
                </Form.Item>
            </Form>
        </Modal>
    );
};

export default SshKeyListModal;